/*
 ------------------------------------------------------------------------------
 Copyright (C) 1996-2001 Id Software, Inc.

 This file is part of the Quake source code.

 The Quake source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quake source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quake source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// vector.cpp - vector math library
//


#include "../shared.h"


glqVec2		vec2_origin(0.0f, 0.0f);
glqVec3		vec3_origin(0.0f, 0.0f, 0.0f);
glqVec4		vec4_origin(0.0f, 0.0f, 0.0f, 0.0f);
glqVec5		vec5_origin(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);


/*
 ==============================================================================

 2D VECTOR

 ==============================================================================
*/


/*
 ==================
 glqVec2::ToString

 This is just a convenience function for printing vectors
 ==================
*/
const char *glqVec2::ToString (int precision) const {

	return Str_FromFloatArray(ToFloatPtr(), 2, precision);
}


/*
 ==============================================================================

 3D VECTOR

 ==============================================================================
*/


/*
 ==================
 glqVec3::NormalVectors

 Given a normalized forward vector, create two other perpendicular vectors
 ==================
*/
void glqVec3::NormalVectors (glqVec3 &right, glqVec3 &up) const {

	float	d;

	// This rotate and negate guarantees a vector not colinear with the
	// original
	right.Set(z, -x, y);

	d = right.Dot(*this);
	right -= (*this * d);
	right.Normalize();

	up.Cross(right, *this);
}

/*
 ==================
 glqVec3::ToPitch
 ==================
*/
float glqVec3::ToPitch (void) const {

	float	pitch;

	if (x == 0.0f && y == 0.0f){
		if (z > 0.0f)
			pitch = 90.0f;
		else
			pitch = 270.0f;
	}
	else {
		pitch = RAD2DEG(glqMath::ATan(z, glqMath::Sqrt(x*x + y*y)));
		if (pitch < 0.0f)
			pitch += 360.0f;
	}

	return pitch;
}

/*
 ==================
 glqVec3::ToYaw
 ==================
*/
float glqVec3::ToYaw (void) const{

	float	yaw;

	if (x == 0.0f && y == 0.0f)
		yaw = 0.0f;
	else {
		yaw = RAD2DEG(glqMath::ATan(y, x));
		if (yaw < 0.0f)
			yaw += 360.0f;
	}

	return yaw;
}

/*
 ==================
 glqVec3::ToAngles
 ==================
*/
glqAngles glqVec3::ToAngles (void) const {

	float	pitch, yaw;

	if (x == 0.0f && y == 0.0f){
		yaw = 0.0f;

		if (z > 0.0f)
			pitch = 90.0f;
		else
			pitch = 270.0f;
	}
	else {
		yaw = RAD2DEG(glqMath::ATan(y, x));
		if (yaw < 0.0f)
			yaw += 360.0f;

		pitch = RAD2DEG(glqMath::ATan(z, glqMath::Sqrt(x*x + y*y)));
		if (pitch < 0.0f)
			pitch += 360.0f;
	}

	return glqAngles(-pitch, yaw, 0.0f);
}

/*
 ==================
 glqVec3::ToMat3
 ==================
*/
glqMat3 glqVec3::ToMat3 (void) const {

	glqMat3	mat;
	float	d;

	mat[0] = *this;

	d = x*x + y*y;

	if (d){
		d = 1.0f / glqMath::Sqrt(d);

		mat[1][0] = -y * d;
		mat[1][1] = x * d;
		mat[1][2] = 0.0f;
	}
	else {
		mat[1][0] = 1.0f;
		mat[1][1] = 0.0f;
		mat[1][2] = 0.0f;
	}

	mat[2].Cross(mat[0], mat[1]);

	return mat;
}

/*
 ==================
 glqVec3::ToString

 This is just a convenience function for printing vectors
 ==================
*/
const char *glqVec3::ToString (int precision) const {

	return Str_FromFloatArray(ToFloatPtr(), 3, precision);
}


/*
 ==============================================================================

 4D VECTOR

 ==============================================================================
*/


/*
 ==================
 glqVec4::ToString

 This is just a convenience function for printing vectors
 ==================
*/
const char *glqVec4::ToString (int precision) const {

	return Str_FromFloatArray(ToFloatPtr(), 4, precision);
}


/*
 ==============================================================================

 5D VECTOR

 ==============================================================================
*/


/*
 ==================
 glqVec5::ToString

 This is just a convenience function for printing vectors
 ==================
*/
const char *glqVec5::ToString (int precision) const {

	return Str_FromFloatArray(ToFloatPtr(), 5, precision);
}